﻿using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Inovout.Data.Domain;

namespace System.Web.Mvc
{
    public class FilterCriteriaColllectionBuilder<TModel> : IEnumerable<FilterCriteria>
    {
        public FilterCriteriaColllectionBuilder(IEnumerable<FilterCriteria> filters = null)
        {
            this.Filters = new List<FilterCriteria>();
            if (filters != null)
            {
                this.Filters.AddRange(filters);
            }
        }
        public List<FilterCriteria> Filters { get; private set; }
        public FilterCriteriaColllectionBuilder<TEntity> OfType<TEntity>()
        {
            return new FilterCriteriaColllectionBuilder<TEntity>();
        }
        public FilterCriteriaColllectionBuilder<TModel> FilterFor<TProperty>(Expression<Func<TModel, TProperty>> filterPropertyNameExpression, dynamic filterValue = null)
        {
            return this.FilterFor(filterPropertyNameExpression, FilterOperation.Eq, filterValue);
        }
        public FilterCriteriaColllectionBuilder<TModel> FilterFor<TProperty>(Expression<Func<TModel, TProperty>> filterPropertyNameExpression, FilterOperation filterOperation, dynamic filterValue = null)
        {
            this.Filters.Add(new FilterCriteria(GetPropertyName(filterPropertyNameExpression), filterOperation, filterValue == null ? null : filterValue.ToString()));
            return this;
        }
        private string GetPropertyName<TProperty>(Expression<Func<TModel, TProperty>> propertyNameExpression)
        {
            string propertyName = ExpressionHelper.GetExpressionText(propertyNameExpression);
            if (typeof(DataObject).IsAssignableFrom(typeof(TProperty)))
            {
                propertyName += ".Id";
            }
            return propertyName;
        }

        public FilterCriteriaColllectionBuilder<TModel> Merge(IEnumerable<FilterCriteria> filters)
        {
            if (filters != null)
            {
                foreach (var filter in filters)
                {
                    var buildFilter = this.Filters.SingleOrDefault(f => f.FilterName.Equals(filter.FilterName) && f.FilterOperation.Equals(filter.FilterOperation));
                    if (buildFilter == null)
                    {
                        this.Filters.Add(filter);
                    }
                    else
                    {
                        buildFilter.FilterValue = filter.FilterValue;
                    }
                }
            }
            return this;
        }

        public IEnumerator<FilterCriteria> GetEnumerator()
        {
            return this.Filters.GetEnumerator();
        }

        Collections.IEnumerator Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }

}
